import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { NzModalService } from 'ng-zorro-antd/modal';
import snq from 'snq';
import { EditState } from '../../core';
import { IdentityRoleDto, IdentityUserDto, IdentityUserService } from '../proxy/identity';
import { NzMessageService } from 'ng-zorro-antd/message';
import { RefSelectUserService } from '../ref-select-user/ref-select-user.service';
import { RefPermissionService } from '../ref-permission/ref-permission.service';
import { UserDetailComponentService } from './user-detail.component.service';
import { SubscriptionService } from '@abp/ng.core';

@Component({
  selector: 'lib-user-detail',
  templateUrl: './user-detail.component.html',
  styleUrls: ['./user-detail.component.less'],
})
export class UserDetailComponent implements OnInit {
  entityConfig = {
    defaultValue: {
      lockoutEnabled: false,
      isActive: true,
    },
  };
  editState: EditState;
  validateForm: FormGroup;
  roles: Array<{
    label: string;
    value: string;
    checked?: boolean;
    model: IdentityRoleDto;
    formControl: FormControl;
  }>;
  currentEntity: IdentityUserDto;

  get userNameInputDisabled() {
    return this.editState != EditState.Empty && this.editState != EditState.Creating;
  }

  get showPasswordInput() {
    return this.editState == EditState.Empty || this.editState == EditState.Creating;
  }

  get roleGroups(): FormGroup[] {
    return ((this.validateForm.get('roleNames') as FormArray)?.controls as FormGroup[]) || [];
  }

  get mappedRoleNames() {
    const { roleNames = [] } = this.validateForm.value;
    return (
      roleNames.filter(role => !!role[Object.keys(role)[0]]).map(role => Object.keys(role)[0]) || []
    );
  }

  get permissionBtnDisabled() {
    return this.editState == EditState.Empty || this.editState == EditState.Creating;
  }

  constructor(
    public fb: FormBuilder,
    public entityService: IdentityUserService,
    public refEntityService: RefSelectUserService,
    public refPermissionService: RefPermissionService,
    public modal: NzModalService,
    public message: NzMessageService,
    public router: Router,
    public componentService: UserDetailComponentService,
    public subscription: SubscriptionService
  ) {}

  ngOnInit(): void {
    this.editState = EditState.Empty;
    this.currentEntity = this.entityConfig.defaultValue as IdentityUserDto;
    this.validateForm = this.fb.group({
      userName: [this.entityConfig.defaultValue['userName']],
      name: [this.entityConfig.defaultValue['name']],
      email: [this.entityConfig.defaultValue['email']],
      phoneNumber: [this.entityConfig.defaultValue['phoneNumber']],
      lockoutEnabled: [this.entityConfig.defaultValue['lockoutEnabled']],
      isActive: [this.entityConfig.defaultValue['isActive']],
    });

    this.validateForm.valueChanges.subscribe(_ => {
      if (this.editState == EditState.Empty) {
        this.editState = EditState.Creating;
      } else if (this.editState == EditState.View) {
        this.editState = EditState.Editing;
      }
    });

    this.addPasswordControl();
    this.entityService.getAssignableRoles().subscribe(result => {
      this.roles = snq(() =>
        result.items.map(role => {
          return {
            label: role.name,
            value: role.id,
            checked: role.isDefault,
            model: role,
            formControl: new FormControl(role.isDefault),
          };
        })
      );

      var roleNamesGroup: FormGroup[] = [];
      for (var role of this.roles) {
        roleNamesGroup.push(this.fb.group({ [role.label]: role.formControl }));
      }
      this.validateForm.addControl('roleNames', this.fb.array(roleNamesGroup), {
        emitEvent: false,
      });
    });

    this.subscription.addOne(this.componentService.OnNew, () => this.new());
    this.subscription.addOne(this.componentService.OnView, model => {
      if (!!model && !!model.id) {
        this.entityService.get(model.id).subscribe(entity => {
          if (!!entity) {
            this.setCurrentEntity(entity);
          } else {
            this.message.info(`未找到ID为${model.id}的用户。`);
          }
        });
      }
    });
  }

  save() {
    if (this.editState == EditState.Creating) {
      this.entityService
        .create({ ...this.validateForm.value, roleNames: this.mappedRoleNames })
        .subscribe(entity => {
          if (!!entity) {
            this.setCurrentEntity(entity);
            this.message.success('添加成功!');
          }
        });
    } else if (this.editState == EditState.Editing) {
      this.entityService
        .update(this.currentEntity.id, {
          ...this.currentEntity,
          ...this.validateForm.value,
          roleNames: this.mappedRoleNames,
        })
        .subscribe(entity => {
          if (!!entity) {
            this.setCurrentEntity(entity);
            this.message.success('编辑成功!');
          }
        });
    }
  }

  giveup() {
    this.giveUpConfirm().then(_ => {
      if (this.editState == EditState.Creating) {
        //表单状态为创建时，清空数据
        this.changeToEmpty();
      } else if (this.editState == EditState.Editing) {
        //表单状态为编辑时，恢复原数据
        this.setCurrentEntity(this.currentEntity);
      }
    });
  }

  new() {
    this.checkDirty().then(_ => this.changeToEmpty());
  }

  copy() {
    this.checkDirty().then(_ => {
      this.setCurrentEntity(this.currentEntity);
      this.currentEntity = this.entityConfig.defaultValue as IdentityUserDto;
      this.editState = EditState.Creating;

      this.addPasswordControl();
    });
  }

  delete() {
    this.modal.confirm({
      nzTitle: '提示信息',
      nzContent: '您确认删除当前记录么？',
      nzOkText: '确认',
      nzCancelText: '取消',
      nzOnOk: () => {
        this.entityService.delete(this.currentEntity.id).subscribe(_ => this.changeToEmpty());
      },
    });
  }

  select() {
    this.refEntityService.show().subscribe(entitys => {
      if (entitys?.length) this.setCurrentEntity(entitys[0]);
    });
  }

  list() {
    this.router.navigate(['identity/user-list']);
  }

  editPermission() {
    this.refPermissionService.show({ providerName: 'U', keyModel: this.currentEntity }).subscribe();
  }

  refresh() {}

  search(userName) {
    this.entityService.findByUsername(userName).subscribe(entity => {
      if (!!entity) {
        this.setCurrentEntity(entity);
      } else {
        this.message.info(`未找到用户名为${userName}的用户。`);
      }
    });
  }

  protected changeToEmpty() {
    this.validateForm.reset(this.entityConfig.defaultValue, { emitEvent: false });
    this.editState = EditState.Empty;

    this.addPasswordControl();
    this.roles.forEach(x => x.formControl.setValue(x.checked, { emitEvent: false }));
  }

  protected setCurrentEntity(entity: IdentityUserDto) {
    this.currentEntity = entity;
    this.validateForm.reset(this.currentEntity, { emitEvent: false });
    this.editState = EditState.View;

    this.removePasswordControl();
    this.entityService.getRoles(entity.id).subscribe(({ items }) => {
      this.roles.forEach(x => {
        if (items.find(item => item.id == x.value) != null) {
          x.formControl.setValue(true, { emitEvent: false });
        } else {
          x.formControl.setValue(false, { emitEvent: false });
        }
      });
    });
  }

  protected giveUpConfirm(): Promise<any> {
    return new Promise((resolve, reject) => {
      if (this.editState != EditState.Creating && this.editState != EditState.Editing)
        return reject();
      this.modal.confirm({
        nzTitle: '提示信息',
        nzContent: '您确认要放弃未保存的修改么？',
        nzOkText: '确认',
        nzCancelText: '取消',
        nzOnOk: () => resolve(null),
      });
    });
  }

  protected checkDirty(): Promise<any> {
    return new Promise(resolve => {
      if (this.editState == EditState.Creating || this.editState == EditState.Editing) {
        this.modal.confirm({
          nzTitle: '提示信息',
          nzContent: '您有未保存的修改，确认要放弃未保存的修改么？',
          nzOkText: '确认',
          nzCancelText: '取消',
          nzOnOk: () => resolve(null),
        });
      } else {
        resolve(null);
      }
    });
  }

  protected addPasswordControl() {
    if (!this.validateForm.controls['password']) {
      this.validateForm.addControl(
        'password',
        new FormControl(null, [Validators.required, Validators.minLength(6)]),
        { emitEvent: false }
      );
    }
  }

  protected removePasswordControl() {
    if (!!this.validateForm.controls['password']) {
      this.validateForm.removeControl('password', { emitEvent: false });
    }
  }
}
